[SuperEditor] Add toggleable headers (Resolves #2276) #2404
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
[SuperEditor] Add toggleable headers. Resolves #2276
This PR adds the ability to group nodes together under header nodes or list item nodes, where each group can be collapsed/expanded by tapping on a button near it.
The groups are created upon initialization, when adding or removing a node, and when changing a node that couldn’t start a group to a node that can start a group. For example, typing "# " at the beginning of a paragraph converts it to a header node and creates a new group.
Navigating using the arrow keys skips nodes inside a collapsed group. For example, pressing ARROW DOWN skips nodes that are inside a collapsed group.
The user cannot start or end a selection inside a collapsed group. Also, if the selection starts or ends within a group and the user collapses the group, the selection is adjusted to avoid starting or ending inside the collapsed group.
Node grouping is customizable and apps can implement their own grouping logic, if desirable.
Implementation
A
GroupBuilderinterface was added with the methods required to grouping nodes:canStartGroup: to signal the document layout that the current node can start a group, for example, when it is a level one header.canAddToGroup: to signal the document layout that a node can be added to an existing group.build: to create the widget for this group.SuperEditorwill take a list ofGroupBuilders as a constructor parameter.Previously, all components were organized into a vertical list of components inside the
SingleColumnDocumentLayout. Now, whenever aGroupBuilderreturnstrueforcanStartGroup, the document layout will callcanAddToGroupto each node below it, untilcanAddToGroupreturnsfalse. After gathering all nodes that are part of the group,SingleColumnDocumentLayoutcallsbuildon theGroupBuilderto create a widget subtree for that group.To handle the key navigation, at the current state of this PR, it was added an
isComponentVisiblemethod to theDocumentLayoutinterface, so the layout can report that a component is not currently visible. This is yet subject to change, depending on how we expose an API to programmatically collapse/expand/check state of a group.This PR adds
HeaderGroupBuilderandListItemGroupBuilderwith default behavior for headers and list items. All customization can be done using constructor parameters for these builders. For example, customizing the toggle button, restricting the maximum number of children of a group, etc.ToggleableGroupis the default widget used for headers and list items, which includes a default button that fades in when the mouse enters, fades out when the mouse leaves, animates upon tap. It also includes a vertical line below the button, that also fades in/out. The widget can optionally animate the expanding/collapsing of a group.A change that might be regrettable is that I changed
_SingleColumnDocumentLayoutStateto be public, so I can access information about groups inside tests. Once we figure out a public API for that this can be reverted.Remaining work
Screen.Recording.2024-11-11.at.16.23.53.mov